﻿#ifndef FUN_HPP
#define FUN_HPP
#include "rc4.h"
/* some function */

// // 網絡請求(高級) // //
class Http {
private:
    QMap<QString, QString> requestHeader = {
        {"accept-language", "zh-CN,zh;q=0.9"},
        {"User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"} };
    int redirectCount = 0;
    QList<QNetworkCookie> allCookie, receiveCookie;
    QNetworkReply::NetworkError error;
    QByteArray resData;
    int statusCode=-1;
    struct HTTP_HEADER{
        QString name;
        QString value;
    };
    QList<HTTP_HEADER> headerList;

public:
    int timeout=6000;
    QNetworkAccessManager* manager=nullptr;
    Http()
    {
        newManager();
    }
    ~Http(){
        deleteManager();
    }
    void newManager(){
        if(manager==nullptr) manager = new QNetworkAccessManager();
    }
    void deleteManager(){
        if(manager){
            delete manager;
            manager = nullptr;
        }
    }
    int get(QString urlTmp = "") {
        resData="";
        if(manager==nullptr)  {return 404;}
        QNetworkCookieJar *cookieJar = manager->cookieJar();
        cookieJar->setCookiesFromUrl(allCookie, QUrl(urlTmp));
        QNetworkReply* pReplay;
        QNetworkRequest* request = new QNetworkRequest();
        request->setTransferTimeout(timeout);
        if (urlTmp.size() > 0) request->setUrl(QUrl(urlTmp));
        for (QMap<QString, QString>::iterator it = requestHeader.begin(); it != requestHeader.end(); it++)
            request->setRawHeader(it.key().toUtf8(), it.value().toUtf8());
        //if (allCookie.size() > 0) request->setHeader(QNetworkRequest::CookieHeader, QVariant::fromValue(allCookie));
        //if(!request->header(QNetworkRequest::ContentTypeHeader).toBool())
            //request->setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
        QSslConfiguration cfg = request->sslConfiguration();
        cfg.setPeerVerifyMode(QSslSocket::VerifyNone);
        cfg.setProtocol(QSsl::AnyProtocol);
        request->setSslConfiguration(cfg);
        pReplay = manager->get(*request);
        while (!pReplay->isFinished()) {
            qApp->processEvents(); // 處理事件循環，防止界面卡死
            Sleep(10);
        }
        delete request;
        // 保存狀態碼、結果、響應頭
        statusCode = 404;
        if (pReplay->error() == QNetworkReply::NoError){
            statusCode = pReplay->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
            resData = pReplay->readAll();
            QString url302=pReplay->attribute(QNetworkRequest::RedirectionTargetAttribute).toString();
            if(!receiveCookie.empty()) receiveCookie.clear();
            receiveCookie = pReplay->manager()->cookieJar()->cookiesForUrl(pReplay->url());
            QList<QByteArray> headerKeys = pReplay->rawHeaderList();
            if(!headerList.empty())headerList.clear();
            foreach (const QByteArray &headerKey, headerKeys) {
                QByteArray headerValue = pReplay->rawHeader(headerKey);
                headerList.push_back({headerKey, headerValue});
            }
            pReplay->deleteLater();
            if (statusCode == 302 && redirectCount > 0 && url302.indexOf("http")!=-1) {
                redirectCount--;
                statusCode = get(url302);
            }
        }
        return statusCode;
    }
    int post(QString urlTmp = "", QByteArray val = "") {
        resData="";
        if(manager==nullptr)  return 404;
        QNetworkCookieJar *cookieJar = manager->cookieJar();
        cookieJar->setCookiesFromUrl(allCookie, QUrl(urlTmp));
        QNetworkReply* pReplay;
        QNetworkRequest* request = new QNetworkRequest();
        request->setTransferTimeout(timeout);
        if (urlTmp.size() > 0) request->setUrl(QUrl(urlTmp));
        for (QMap<QString, QString>::iterator it = requestHeader.begin(); it != requestHeader.end(); it++){
            request->setRawHeader(it.key().toUtf8(), it.value().toUtf8());
        }
        //if (allCookie.size() > 0) request->setHeader(QNetworkRequest::CookieHeader, QVariant::fromValue(allCookie));
        //if(!request->header(QNetworkRequest::ContentTypeHeader).toBool())
            //request->setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
        QSslConfiguration cfg = request->sslConfiguration();
        cfg.setPeerVerifyMode(QSslSocket::VerifyNone);
        cfg.setProtocol(QSsl::AnyProtocol);
        request->setSslConfiguration(cfg);
        pReplay = manager->post(*request, val);
        while (!pReplay->isFinished()) {
            qApp->processEvents(); // 處理事件循環，防止界面卡死
            //if (QThread::currentThread() != qApp->thread())
            Sleep(10);
        }
        delete request;
        // 保存狀態碼、結果、響應頭
        statusCode = 404;
        if (pReplay->error() == QNetworkReply::NoError){
            statusCode = pReplay->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
            resData = pReplay->readAll();
            QString url302=pReplay->attribute(QNetworkRequest::RedirectionTargetAttribute).toString();
            if(!receiveCookie.empty()) receiveCookie.clear();
            receiveCookie = pReplay->manager()->cookieJar()->cookiesForUrl(pReplay->url());
            QList<QByteArray> headerKeys = pReplay->rawHeaderList();
            if(!headerList.empty())headerList.clear();
            foreach (const QByteArray &headerKey, headerKeys) {
                QByteArray headerValue = pReplay->rawHeader(headerKey);
                headerList.push_back({headerKey, headerValue});
            }
            pReplay->deleteLater();
            if (statusCode == 302 && redirectCount > 0 && url302.indexOf("http")!=-1) {
                redirectCount--;
                statusCode = post(url302);
            }
        }
        return statusCode;
    }
    // 設置302重定向的次數
    void setRedirect(int countTmp) {
        redirectCount = countTmp;
    }
    // 是否有錯誤
    bool isError() {
        return (error != QNetworkReply::NoError);
    }
    // 獲取狀態碼
    int getCode() {
        return statusCode;
    }
    // 獲取結果
    QByteArray getData() {
        return resData;
    }
    void setCookie(QList<QNetworkCookie>& cookieTmp) {
        allCookie += cookieTmp;
    }
    void setCookie(QByteArray name, QByteArray value) {
        foreach (auto cookie, allCookie) {
            if(cookie.name()==name) {cookie.setValue(value); return;}
        }
        QNetworkCookie cookieTmp(name, value);
        allCookie.push_back(cookieTmp);

    }
    QList<QNetworkCookie> getCookie() {
        return receiveCookie;
    }
    QString getCookie(QString name) {
        foreach (auto cookie, receiveCookie) {
            if(cookie.name()==name) return cookie.value();
        }
        return "";
    }
    void clearCookie() {
        if (!allCookie.empty()) allCookie.clear();
    }
    void clearHeader() {
        if (!headerList.empty()) headerList.clear();
    }
    QString GetHeader(QByteArray name) {
        foreach (auto a, headerList) {
            if(a.name==name) return a.value;
        }
        return "";
    }
    void AddHeader(QString fieldStr, QString valueStr, bool isClear = false) {
        if (isClear && requestHeader.size() > 0)  requestHeader.clear();
        requestHeader.insert(fieldStr, valueStr);
    }
    void AddHeader(QMap<QString, QString> hTmp) {
        if (requestHeader.size() > 0)  requestHeader.clear();
        requestHeader.swap(hTmp);
    }
    // // 網絡請求(直接) // //
public:
    inline QNetworkReply* HttpGetReply(QString url)
    {
        resData="";
        if(manager==nullptr)  return nullptr;
        QNetworkCookieJar *cookieJar = manager->cookieJar();
        cookieJar->setCookiesFromUrl(allCookie, QUrl(url));
        QString baseUrl = url;
        QNetworkRequest request(baseUrl);
        request.setTransferTimeout(timeout);
        for (QMap<QString, QString>::iterator it = requestHeader.begin(); it != requestHeader.end(); it++)
            request.setRawHeader(it.key().toUtf8(), it.value().toUtf8());
        QSslConfiguration cfg = request.sslConfiguration();
        QNetworkReply* pReplay = manager->get(request);
        while (!pReplay->isFinished()) {
            qApp->processEvents(); // 處理事件循環，防止界面卡死
            Sleep(10);
        }
        return pReplay;
    }

    inline QByteArray HttpGet(QString url)
    {
        resData="";
        if(manager==nullptr)  return "";
        QNetworkCookieJar *cookieJar = manager->cookieJar();
        cookieJar->setCookiesFromUrl(allCookie, QUrl(url));
        QString baseUrl = url;
        QNetworkRequest request(baseUrl);
        request.setTransferTimeout(timeout);
        for (QMap<QString, QString>::iterator it = requestHeader.begin(); it != requestHeader.end(); it++)
            request.setRawHeader(it.key().toUtf8(), it.value().toUtf8());
        QSslConfiguration cfg = request.sslConfiguration();
        cfg.setPeerVerifyMode(QSslSocket::VerifyNone);
        cfg.setProtocol(QSsl::AnyProtocol);
        request.setSslConfiguration(cfg);
        // 發送請求
        QNetworkReply* pReplay = manager->get(request);
        while (!pReplay->isFinished()) {
            qApp->processEvents(); // 處理事件循環，防止界面卡死
            Sleep(10);
        }
        //獲取響應信息
        QByteArray res = pReplay->readAll();
        statusCode = pReplay->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
        pReplay->deleteLater();
        return res;
    }

    inline QByteArray HttpPost(QString url, QString data)
    {
        resData="";
        if(manager==nullptr)  return "";
        QNetworkCookieJar *cookieJar = manager->cookieJar();
        cookieJar->setCookiesFromUrl(allCookie, QUrl(url));
        QNetworkRequest qnr(url);
        qnr.setTransferTimeout(timeout);
        for (QMap<QString, QString>::iterator it = requestHeader.begin(); it != requestHeader.end(); it++)
            qnr.setRawHeader(it.key().toUtf8(), it.value().toUtf8());
        qnr.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
        QSslConfiguration cfg = qnr.sslConfiguration();
        cfg.setPeerVerifyMode(QSslSocket::VerifyNone);
        cfg.setProtocol(QSsl::AnyProtocol);
        qnr.setSslConfiguration(cfg);
        QNetworkReply* reply = manager->post(qnr, data.toUtf8());
        while (!reply->isFinished()) {
            qApp->processEvents(); // 處理事件循環，防止界面卡死
            Sleep(10);
        }
        QByteArray res = reply->readAll();
        statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
        reply->deleteLater();
        reply = nullptr;
        return res;
    }
    inline QString HttpGetHeader(QString link, QByteArray headerName)
    {
        resData="";
        if(manager==nullptr)  return "";
        QNetworkCookieJar *cookieJar = manager->cookieJar();
        cookieJar->setCookiesFromUrl(allCookie, QUrl(link));
        QNetworkRequest qnr(link);
        qnr.setTransferTimeout(timeout);
        for (QMap<QString,QString>::iterator it = requestHeader.begin(); it!=requestHeader.end(); it++)
            qnr.setRawHeader(it.key().toUtf8(), it.value().toUtf8());
        QSslConfiguration cfg = qnr.sslConfiguration();
        cfg.setPeerVerifyMode(QSslSocket::VerifyNone);
        cfg.setProtocol(QSsl::AnyProtocol);
        qnr.setSslConfiguration(cfg);
        QNetworkReply* reply = manager->head(qnr);
        while (!reply->isFinished()) {
            qApp->processEvents(); // 處理事件循環，防止界面卡死
            Sleep(10);
        }
        QString var = reply->rawHeader(headerName);
        statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
        reply->deleteLater();
        reply = nullptr;
        return var;
    }
    inline QString HttpGetHeader(QString link, enum QNetworkRequest::KnownHeaders headerName)
    {
        resData="";
        if(manager==nullptr)  return "";
        QNetworkCookieJar *cookieJar = manager->cookieJar();
        cookieJar->setCookiesFromUrl(allCookie, QUrl(link));
        QNetworkRequest qnr(link);
        qnr.setTransferTimeout(timeout);
        for (QMap<QString, QString>::iterator it = requestHeader.begin(); it != requestHeader.end(); it++)
            qnr.setRawHeader(it.key().toUtf8(), it.value().toUtf8());
        QSslConfiguration cfg = qnr.sslConfiguration();
        cfg.setPeerVerifyMode(QSslSocket::VerifyNone);
        cfg.setProtocol(QSsl::AnyProtocol);
        qnr.setSslConfiguration(cfg);
        QNetworkReply* reply = manager->head(qnr);
        while (!reply->isFinished()) {
            qApp->processEvents(); // 處理事件循環，防止界面卡死
            Sleep(10);
        }
        QString var = reply->header(headerName).toString();
        statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
        reply->deleteLater();
        reply = nullptr;
        return var;
    }
    inline qint64 HttpGetSize(QString link)
    {
        return HttpGetHeader(link, QNetworkRequest::ContentLengthHeader).toLongLong();
    }
};


#endif // FUN_HPP
